package cn.ges.bean;

import cn.ges.json.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.Contract;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @author gespent@163.com
 * @date 2018/12/27
 */
@Slf4j
@SuppressWarnings(value = {"unchecked"})
public class BeanUtil {

    public static <T> T map2bean(HashMap map, Class<T> tClass) {
        String s = JsonUtil.objectToJson(map);
        return JsonUtil.jsonToObject(s, tClass);
    }

    @Contract("null->fail")
    public static <T> T beanClone(T source) throws IllegalAccessException, InstantiationException {
        final Class<?> aClass = source.getClass();
        final Field[] declaredFields = aClass.getDeclaredFields();
        final Object o = aClass.newInstance();
        Arrays.stream(declaredFields).forEach(a -> {
            a.setAccessible(true);
            try {
                a.set(o, a.get(source));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        });
        return (T) o;
    }


    /**
     * Bean --> Map 1: 利用Introspector和PropertyDescriptor 将Bean --> Map
     *
     * @param obj 被转换的bean
     * @return map
     */
    @Contract("null->null")
    public static HashMap<Object, Object> bean2Map(Object obj) {

        if (obj == null) {
            return null;
        }
        HashMap<Object, Object> map = new HashMap<>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                // 过滤class属性
                if (!"class".equals(key)) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);
                    map.put(key, value);
                }

            }
        } catch (Exception e) {
            return null;
        }

        return map;

    }

    public static HashMap<String, Object> castMap(Map<Object, Object> map) {
        HashMap<String, Object> castMap = new HashMap<>(map.size());
        for (Object o : map.keySet()) {
            castMap.put((String) o, map.get(o));
        }
        return castMap;
    }
}
